<template>
  <div class="sign-wrap">
    <a-form :model="formState" layout="vertical" class="sign-form">
      <div class="sign-form-title">CDN 管理系统</div>
      <div class="sign-form-container">
        <a-form-item hide-label>
          <a-input
            v-model="formState.account"
            placeholder="请输入账号"
            size="large"
            class="!px-4"
            @input="accountError = ''">
            <template #prefix>
              <i-icons-account />
            </template>
          </a-input>
        </a-form-item>
        <a-form-item hide-label>
          <section class="flex flex-col w-full gap-y-4">
            <a-input-password
              v-model.trim="formState.password"
              placeholder="请输入密码"
              size="large"
              class="!px-4 cloud-pwd-icon"
              @change="accountError = ''"
              @keyup.enter="handleSubmit"
              @input="handlePasswordInput">
              <template #prefix> <i-icons-lock /> </template>
            </a-input-password>
            <div v-if="accountError" class="flex items-center gap-x-6px">
              <i-icons-danger />
              <span class="text-#ED3C3C text-sx/5">{{ accountError }}</span>
            </div>
          </section>
        </a-form-item>
        <section class="w-full mt-6">
          <a-button
            type="primary"
            size="large"
            class="w-full"
            :disabled="isDisabled"
            :loading="loading"
            @click="handleSubmit">
            登录
          </a-button>
        </section>
      </div>
      <div>
        <img src="@/assets/images/logo.png" class="w-[78px] h-5" calt="" />
      </div>
    </a-form>
    <div class="sign-desc">
      <div class="sign-desc-content">
        <div class="desc-item">
          <div class="desc-item-icon">
            <img src="@/assets/images/deploy.png" alt="" srcset="" />
          </div>
          <div class="desc-item-wrap">
            <div class="title">简单易用</div>
            <div class="desc">一键安装部署，快速简单使用</div>
          </div>
        </div>
        <div class="desc-item">
          <div class="desc-item-icon">
            <img src="@/assets/images/safe.png" alt="" srcset="" />
          </div>
          <div class="desc-item-wrap">
            <div class="title">安全可靠</div>
            <div class="desc">数据全面私有，安全尽在掌握</div>
          </div>
        </div>
        <div class="desc-item">
          <div class="desc-item-icon">
            <img src="@/assets/images/monitor.png" alt="" srcset="" />
          </div>
          <div class="desc-item-wrap">
            <div class="title">实时监测</div>
            <div class="desc">实时监测系统关键指标，及时掌握业务波动</div>
          </div>
        </div>
      </div>
    </div>
    <visual-shield
      ref="visualShieldRef"
      :request="behavioralCaptcha"
      :verify="handleVerify" />
    <upgrade-status
      v-model:visible="imprintVisible"
      v-model:status="UpStatus" />
  </div>
</template>
<script lang="ts" setup>
import { useAppStore } from '@/stores/app'
import { ResultEnum } from '@/apis/http'
import { updateApiSystemUpdateStatusApi } from '@/apis/modules/resolve/version'
import UpgradeStatus from './components/UpgradeStatus.vue'
import {
  getApiCaptchaImageApi,
  getCaptchaPreCheckApi,
  postApiCaptchaVerifyApi,
  postApiLoginApi
} from '@/apis/modules/auth'
import {
  useBehavioralCaptcha,
  type RequestFnOptions,
  type VerifyOptions,
  type VisualShieldInstance
} from '@/components/visual-shield'
const visualShieldRef = ref<VisualShieldInstance>()
const router = useRouter()
const appStore = useAppStore()
const formState = reactive({
  account: '',
  password: ''
})
const UpStatus = ref(1)
const behavioralCaptchaKey = ref('')
const accountError = ref<string>('')
const loading = ref(false)
const isDisabled = computed<boolean>(
  () =>
    !formState.password ||
    !formState.account ||
    loading.value ||
    !!accountError.value
)
const { visible: imprintVisible, open: open } = usePopup()

const handleLogin = () => {
  loading.value = true
  const data = {
    account: formState.account,
    captcha_key: behavioralCaptchaKey.value,
    password: formState.password
  }
  postApiLoginApi(data)
    .then((res: any) => {
      if (res.code === ResultEnum.SUCCESS) {
        appStore.saveToken(res.data.token)
        appStore.saveUserInfo(res.data.user_info)
        accountError.value = ''
        router.replace('/')
      } else if (
        [
          ResultEnum.WRONG_PASSWORD,
          ResultEnum.ACCOUNT_NOT_EXIST,
          ResultEnum.WRONG_ACCOUNT_ERROR
        ].includes(res.code)
      ) {
        accountError.value = res.message ?? '账号或密码不正确,请重试'
      } else {
        ToastUtils.error(res.message)
      }
    })
    .finally(() => (loading.value = false))
}

const { withInterceptor } = useBehavioralCaptcha(visualShieldRef, handleLogin)

// 生成行为验证码
const behavioralCaptcha = ({
  loading,
  onSuccess,
  onError,
  onFrequent
}: RequestFnOptions) => {
  loading.value = true
  getApiCaptchaImageApi({ account: formState.account })
    .then((res: any) => {
      if (Number(res.code) === ResultEnum.SUCCESS) {
        const { image_base64, thumb_base64, key } = Object.assign(
          { image_base64: '', thumb_base64: '', key: '' },
          res.data
        )
        onSuccess(image_base64, thumb_base64)
        behavioralCaptchaKey.value = key
      } else if (Number(res.code) === ResultEnum.FREQUENTREQUEST) {
        onFrequent(res?.message)
        const { key } = Object.assign(
          { image_base64: '', thumb_base64: '', key: '' },
          res.data
        )
        behavioralCaptchaKey.value = key
      } else {
        onError(res.message)
      }
    })
    .finally(() => {
      loading.value = false
    })
}

// 验证验证码
const handleVerify = ({ onError, onSuccess, points }: VerifyOptions) => {
  postApiCaptchaVerifyApi({
    key: behavioralCaptchaKey.value,
    dots: String(points)
  }).then((res: any) => {
    if (Number(res.code) === ResultEnum.SUCCESS) {
      onSuccess()
    } else {
      onError(res.message)
    }
  })
}
const handlePasswordInput = (val: string) => {
  formState.password = val.replace(/\s/g, '')
  accountError.value = ''
}
const handleSubmit = async () => {
  if (isDisabled.value) return
  getCaptchaPreCheckApi({})
    .then((res) => {
      const needCaptcha = res?.need_captcha
      if (needCaptcha) {
        withInterceptor()
      } else {
        handleLogin()
      }
    })
    .catch(() => {
      withInterceptor()
    })
}
let timer: NodeJS.Timer
const clear = watch(
  () => UpStatus.value,
  (val) => {
    if (val !== 0) {
      clearInterval(timer)
      clear()
    }
  }
)
watchEffect(() => {
  if (UpStatus.value === 0) return pollingStatus()
  clearInterval(timer)
  clear()
})
//获取升级状态
const getUpdateStatusApi = () => {
  updateApiSystemUpdateStatusApi({}).then((res) => {
    if (!res) {
      clearInterval(timer)
      clear()
      imprintVisible.value = false
      return
    }
    if (res?.progress !== 0) return (UpStatus.value = res?.progress || 1)
    UpStatus.value = res?.progress
    appStore.setUpgradeStatus(res?.progress)
    open()
  })
}
async function pollingStatus(times: number = 3) {
  timer = await setInterval(() => {
    clear()
    getUpdateStatusApi()
  }, times * 1000)
}
onMounted(getUpdateStatusApi)
</script>
<style lang="less" scoped>
.sign-wrap {
  @apply w-full h-full flex min-w-1440px;
  background: url('@/assets/images/login-bg.jpg') no-repeat;
  background-position: center;
  background-size: cover;
  :deep(.sign-form) {
    @apply flex flex-col gap-12 items-center w-550px bg-white h-full  flex-shrink-0;
    padding: 240px 100px 40px;
    backdrop-filter: blur(20px);
    &-title {
      @apply text-1 text-28px/36px font-bold w-full;
    }
    &-container {
      @apply w-full flex flex-col items-center gap-6;
      .arco-form-item {
        margin-bottom: 0;
        .arco-form-item-content {
          @apply min-h-12;
        }
        @apply min-h-12;
        .arco-input {
          &::placeholder {
            @apply text-5;
          }
        }
      }
      .arco-input,
      .arco-btn {
        @apply h-12;
      }
      .forget-password {
        @apply mt-2;
        display: flex;
        justify-content: flex-end;
        align-items: center;
        gap: 10px;
        align-self: stretch;
        color: var(---color-text-3, #646a73);
        font-size: 14px;
        font-weight: 400;
        line-height: 22px; /* 157.143% */
        cursor: pointer;
        &:hover {
          color: var(---primary-6, #11429d);
        }
      }
    }
  }
  .sign-desc {
    @apply pl-40 pt-60;
    &-content {
      @apply w-338px h-296px;
      .desc-item {
        @apply w-full h-96px py-6 flex gap-x-6;
        &-icon {
          img {
            @apply w-12 h-12;
          }
        }
        &-wrap {
          @apply flex flex-col gap-y-1;
          .title {
            @apply text-18px/26px font-bold text-1;
          }
          .desc {
            @apply text-sm/22px text-3;
          }
        }
      }
    }
  }
}
</style>
